﻿namespace MainGame.GameScreens
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;

    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;

    using MainGame.Components;

    using XGameLibrary.Input;
    using XGameLibrary.ScreenManager;
    using XGameLibrary.SpriteClasses;
    using XGameLibrary.TileEngine;
    using XGameLibrary.Controls;

    public class GamePlayScreen : BaseGameState
    {
        Engine engine;

        public TileMap map;
        public Player player;
        public AnimatedSprite sprite;
        private QuestionBox Locked;

        private SoundEffectInstance walking;

        private QuestionBox NPCGuide;
        private QuestionBox SoonTM;

        public GamePlayScreen(Game game, GameStateManager manager) :
            base(game, manager)
        {
            this.engine = new Engine(32, 32);
            this.player = new Player(game);
        }

        protected override void LoadContent()
        {
            Texture2D spriteSheet = this.GameRef.Content.Load<Texture2D>(@"Images\Sprites\" +
                this.GameRef.CharacterGeneratorScreen.SelectedGender +
                this.GameRef.CharacterGeneratorScreen.SelectedHair);
            Dictionary<AnimationKey, Animation> animations = new Dictionary<AnimationKey, Animation>();

            Animation animation = new Animation(4, 31, 64, 0, 0);
            animations.Add(AnimationKey.Down, animation);

            animation = new Animation(4, 31, 64, 0, 64);
            animations.Add(AnimationKey.Left, animation);

            animation = new Animation(4, 31, 64, 0, 128);
            animations.Add(AnimationKey.Right, animation);

            animation = new Animation(4, 31, 64, 0, 192);
            animations.Add(AnimationKey.Up, animation);

            this.sprite = new AnimatedSprite(spriteSheet, animations);

            base.LoadContent();

            //Texture2D tilesetTexture = this.GameRef.Content.Load<Texture2D>(@"Images\Tilesets\tilea2");
            //Tileset tileset1 = new Tileset(tilesetTexture, 16, 12, 32, 32);

            //tilesetTexture = this.GameRef.Content.Load<Texture2D>(@"Images\Tilesets\splatter");
            //Tileset tileset2 = new Tileset(tilesetTexture, 8, 8, 32, 32);

            //tilesetTexture = this.GameRef.Content.Load<Texture2D>(@"Images\Tilesets\building");
            //Tileset tileset3 = new Tileset(tilesetTexture, 8, 8, 32, 32);

            Texture2D tilesetTexture = this.GameRef.Content.Load<Texture2D>(@"Images\Tilesets\yard");
            Tileset tileset4 = new Tileset(tilesetTexture, 8, 8, 32, 32);


            List<Tileset> tilesets = new List<Tileset>();
            //tilesets.Add(tileset1);
            //tilesets.Add(tileset2);
            //tilesets.Add(tileset3);
            tilesets.Add(tileset4);


            MapLayer layer = new MapLayer(32, 32);

            using (StreamReader layerFile = new StreamReader(@"TempMaps\yard.txt"))
            {
                for (int y = 0; y < layer.Height; y++)
                {
                    string line = layerFile.ReadLine();
                    string[] tiles = line.Replace(']', ' ').Split('[');

                    for (int x = 0; x < layer.Width; x++)
                    {
                        int tileNum = int.Parse((tiles[x + 1][0]).ToString()) * 8 + int.Parse((tiles[x + 1][2]).ToString());

                        Tile tile = new Tile(tileNum, 0);

                        layer.SetTile(x, y, tile);
                    }
                }
            }

            MapLayer splatter = new MapLayer(32, 32);
            using (StreamReader splatterFile = new StreamReader(@"TempMaps\yardSplatter.txt"))
            {
                for (int y = 0; y < layer.Height; y++)
                {
                    string line = splatterFile.ReadLine();
                    string[] tiles = line.Replace(']', ' ').Split('[');

                    for (int x = 0; x < layer.Width; x++)
                    {
                        if (tiles[x + 1][0] == 'x')
                        {
                            Tile tileTemp = new Tile(8, 0);
                            splatter.SetTile(x, y, tileTemp);
                            continue;
                        }
                        int tileNum = int.Parse((tiles[x + 1][0]).ToString()) * 8 + int.Parse((tiles[x + 1][2]).ToString());

                        Tile tile = new Tile(tileNum, 0);

                        splatter.SetTile(x, y, tile);
                    }
                }
            }

            Tile tileUp = new Tile(7, 0);
            splatter.SetTile(31, 0, tileUp);
            Tile tileDown = new Tile(15, 0);
            splatter.SetTile(31, 1, tileDown);

            List<MapLayer> mapLayers = new List<MapLayer>();
            mapLayers.Add(layer);
            mapLayers.Add(splatter);

            this.map = new TileMap(tilesets, mapLayers);

            this.walking = AnimatedSprite.WalkingOnRock.CreateInstance();

            this.sprite.Position = new Vector2(18 * 32, 18 * 32);
            this.player.Camera.LockToSprite(this.sprite);

            Texture2D box = this.GameRef.Content.Load<Texture2D>(@"GUI\questionBox");
            Label question = new Label();
            question.Text = "Locked";
            question.Color = Color.Black;

            this.Locked = new QuestionBox(box, question);

            this.Locked.Visible = false;
            this.ControlManager.Add(this.Locked);

            Label questionNPC = new Label();
            questionNPC.Text = "Class has already started!";
            questionNPC.Color = Color.Black;
            this.NPCGuide = new QuestionBox(box, questionNPC);

            this.NPCGuide.Visible = false;
            this.ControlManager.Add(this.NPCGuide);

            Label question2S = new Label();
            question2S.Text = "To be continued...";
            question2S.Color = Color.Black;
            this.SoonTM = new QuestionBox(box, question2S);

            this.SoonTM.Visible = false;
            this.ControlManager.Add(this.SoonTM);
        }

        public override void Update(GameTime gameTime)
        {
            this.player.Update(gameTime);
            this.sprite.Update(gameTime);

            Vector2 motion = new Vector2();

            if (InputHandler.KeyDown(Keys.W))
            {
                this.sprite.CurrentAnimation = AnimationKey.Up;
                motion.Y = -1;
            }
            else if (InputHandler.KeyDown(Keys.S))
            {
                this.sprite.CurrentAnimation = AnimationKey.Down;
                motion.Y = 1;
            }

            if (InputHandler.KeyDown(Keys.A))
            {
                this.sprite.CurrentAnimation = AnimationKey.Left;
                motion.X = -1;
            }
            else if (InputHandler.KeyDown(Keys.D))
            {
                this.sprite.CurrentAnimation = AnimationKey.Right;
                motion.X = 1;
            }

            if (motion != Vector2.Zero)
            {
                sprite.IsAnimating = true;
                motion.Normalize();

                if (this.sprite.Position.Y > 1 * 32 && this.sprite.Position.Y < 16 * 32)
                {
                    if (this.sprite.Position.X >= 16 * 32)
                    {
                        if (motion.X > 0)
                        {
                            motion.X = 0;
                        }
                    }
                }
                if (this.sprite.Position.X >= 17 * 32)
                {
                    if (this.sprite.Position.Y >= 0 * 32 && this.sprite.Position.Y <= 17 * 32)
                    {
                        if (motion.Y < 0)
                        {
                            motion.Y = 0;
                        }
                    }
                }
                if (this.sprite.Position.X >= 17 * 32)
                {
                    if (this.sprite.Position.Y >= 0 * 32 && this.sprite.Position.Y < 16 * 32)
                    {
                        if (motion.Y > 0)
                        {
                            motion.Y = 0;
                        }
                    }
                }

                if (this.sprite.Position.X >= 30 * 32)
                {
                    if (this.sprite.Position.Y >= 0 * 32 && this.sprite.Position.Y <= 1 * 32)
                    {
                        if (motion.X > 0)
                        {
                            motion.X = 0;
                            if (this.player.stamina >= 50)
                            {
                                this.NPCGuide.Visible = true;
                                this.player.masterKey = true;
                            }
                        }
                    }
                }
                else
                {
                    this.NPCGuide.Visible = false;
                }

                if ((this.sprite.Position.Y > 13 * 32 && this.sprite.Position.Y < 15 * 32) && this.sprite.Position.X < 4)
                {
                    if (motion.X < 0)
                    {
                        if (!this.player.masterKey)
                            this.Locked.Visible = true;
                        else
                        {
                            this.SoonTM.Visible = true;
                        }
                    }
                }
                else
                {
                    this.Locked.Visible = false;
                    this.SoonTM.Visible = false;
                }

                if ((this.sprite.Position.Y > 27 * 32 && this.sprite.Position.Y < 29 * 32) && this.sprite.Position.X > 31 * 32 - 4)
                {
                    if (motion.X > 0)
                    {
                        this.StateManager.PushState(new HomeScreen(this.GameRef, this.StateManager, player, sprite));
                    }
                }

                this.sprite.Position += motion * this.sprite.Speed;
                this.sprite.LockToMap();

                if (this.player.Camera.CameraMode == CameraMode.Follow)
                {
                    player.Camera.LockToSprite(this.sprite);
                }

                this.walking.Play();
            }
            else
            {
                this.sprite.IsAnimating = false;
                this.sprite.animations[this.sprite.CurrentAnimation].Reset();
            }

            float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (this.player.stamina > 0)
                this.player.stamina = Math.Max(0f, this.player.stamina - deltaTime);

            if (InputHandler.KeyReleased(Keys.F))
            {
                this.player.Camera.ToggleCameraMode();
                if (this.player.Camera.CameraMode == CameraMode.Follow)
                {
                    player.Camera.LockToSprite(this.sprite);
                }
            }

            if (this.player.Camera.CameraMode != CameraMode.Follow)
            {
                if (InputHandler.KeyReleased(Keys.C))
                {
                    this.player.Camera.LockToSprite(this.sprite);
                }
            }

            if (InputHandler.KeyReleased(Keys.Escape))
            {
                this.GameRef.Exit();
            }

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            this.GameRef.SpriteBatch.Begin(
                SpriteSortMode.Immediate,
                BlendState.AlphaBlend,
                SamplerState.PointClamp,
                null,
                null,
                null,
                Matrix.Identity);

            this.map.Draw(this.GameRef.SpriteBatch, this.player.Camera);
            this.sprite.Draw(gameTime, this.GameRef.SpriteBatch, this.player.Camera, this.player.stamina);
            base.Draw(gameTime);
            this.ControlManager.Draw(this.GameRef.SpriteBatch);
            this.GameRef.SpriteBatch.End();
        }
    }
}
